package cn.base.web.gateway.filter;

import cn.base.web.authc.AccessStrategy;
import cn.base.web.gateway.context.ReactiveSecurityContextHolder;
import cn.base.web.gateway.context.SecurityContext;
import cn.base.web.gateway.exception.GatewayAuthException;
import cn.hutool.core.bean.BeanUtil;
import cn.rengy.auth.Authentication;
import cn.rengy.auth.TokenType;
import cn.rengy.auth.entity.principal.Identity;
import cn.rengy.auth.jwt.JwtCreator;
import cn.rengy.isql.DbService;
import cn.rengy.lang.ResultEntity;
import cn.rengy.util.web.RequestUtil;
import io.jsonwebtoken.ClaimsBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.impl.DefaultClaims;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.time.Duration;
import java.util.Date;

/**
 * 全局认证过滤器
 */
@Slf4j
@Component
public class GlobalAuthFilter implements GlobalFilter, Ordered { //, InitializingBean

    @Autowired
    private AccessStrategy accessStrategy;
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        log.info("===GlobalAuthFilter===============================");
        //exchange.getResponse().
        ResultEntity<HttpStatus, Authentication>  resultEntity = accessStrategy.isAccessAllowed(exchange,null);
        //boolean isAllow=resultEntity.isSuccess();
        if(resultEntity==null){
            resultEntity=ResultEntity.fail(HttpStatus.INTERNAL_SERVER_ERROR,"auth error.");
        }

        //3.不允许访问
        if(Boolean.FALSE.equals(resultEntity.isSuccess())) {
            throw new GatewayAuthException(resultEntity.getCode(),resultEntity.getMessage());
        }
        Authentication authentication=resultEntity.getData();
        //调用其他微服务
        ClaimsBuilder claimsBuilder=Jwts.claims().issuer("gateway")//签发主体
                .expiration(new Date(System.currentTimeMillis()+Duration.ofSeconds(10).toMillis()))//过期时间10秒

        ;
        //Identity identity=(Identity)RequestUtil.getPrincipal();
//        ReactiveSecurityContextHolder.getContext().doOnNext(context -> {
//            context.getAuthentication();
//        }).subscribe();
        Identity newIdentity=null;
        if(authentication!=null){
            Identity identity=(Identity)authentication.getPrincipal();
            newIdentity=new Identity();
            BeanUtil.copyProperties(identity,newIdentity);
        }
        //inner认证模块没有引入sgccinentity的bean，Class.forName会报错
        String accessToken= JwtCreator.createToken(claimsBuilder.build(),newIdentity);
        exchange=wrapHeader(exchange,accessToken);
        return chain.filter(exchange);
    }

    private ServerWebExchange wrapHeader(ServerWebExchange serverWebExchange, String token) {
        //重置Authorization
        ServerHttpRequest request =serverWebExchange.getRequest().mutate()
                //.headers(httpHeaders -> httpHeaders.remove(HttpHeaders.AUTHORIZATION))
                .header(HttpHeaders.AUTHORIZATION, TokenType.INNER.concat(token))
                .build();
        //向headers中放文件，记得build
        return serverWebExchange.mutate().request(request).build();
    }



    private final int orderd=Ordered.HIGHEST_PRECEDENCE+100;
    @Override
    public int getOrder() {
        return orderd;
    }

//    @Override
//    public void afterPropertiesSet() throws Exception {
//        init();
//    }

    @Autowired
    private DbService dbService;
//    private void init(){
//        List<SysResourceUriDTO> all=dbService.queryForBeanList("select_all_sysResourceUri_gateway",SysResourceUriDTO.class);
//        List<UriPath> list=new ArrayList<UriPath>(all.size());
//        for(SysResourceUriDTO sysResourceUriDTO:all){
//            UriPath uriPath=new UriPath();
//            uriPath.setUri(sysResourceUriDTO.getUri());
//            uriPath.setMethod(sysResourceUriDTO.getMethod());
//            uriPath.setAuthType(sysResourceUriDTO.getAuthType());
//            String roles=sysResourceUriDTO.getRoles();
//            if(roles!=null&&roles.length()>0){
//                String[] roless = roles.substring(1, roles.length()-1).split(",");
//                uriPath.setRoles(Stream.of(roless).collect(Collectors.toList()));
//            }
//            list.add(uriPath);
//        }
//        UriTree.build(list);
//    }
}
